﻿using MongoDB.Driver;
using System.Linq.Expressions;

namespace Zws.MongoDb
{
    public class MongoDbClientFacade
    {
        private readonly MongoClient _mongoClient;
        private readonly IMongoDatabase _db;
        public MongoDbClientFacade(MongoDbConfig config)
        {
            _mongoClient = new MongoClient(ConnectionStrGen(config));
            _db = _mongoClient.GetDatabase(config.AuthSource);
        }
        //增
        public async Task InsertAsync<T>(List<T> docs)
        {
            IMongoCollection<T> collection = GetCollection<T>();
            await collection.InsertManyAsync(docs);
        }
        public async Task InsertAsync<T>(T docs)
        {
            IMongoCollection<T> collection = GetCollection<T>();
            await collection.InsertOneAsync(docs);
        }

        //删
        public async Task DeleteAsync<T>(Expression<Func<T, bool>> filter)
        {
            IMongoCollection<T> collection = GetCollection<T>();
            await collection.DeleteManyAsync<T>(filter);
        }

        private IMongoCollection<T> GetCollection<T>()
        {
            return _db.GetCollection<T>(typeof(T).Name?.ToString());
        }

        public async Task UpdateOneAsync<T, TItem>(Expression<Func<T, bool>> filter, Expression<Func<T, TItem>> field, TItem value)
        {
            var update = new UpdateDefinitionBuilder<T>().Set(field, value);
            IMongoCollection<T> collection = GetCollection<T>();
            await collection.UpdateOneAsync<T>(filter, update);
        }
        public async Task UpdateOneAsync<T>(Expression<Func<T, bool>> filter, Func<UpdateDefinitionBuilder<T>, UpdateDefinition<T>> updateBuilder)
        {
            var update = updateBuilder(new UpdateDefinitionBuilder<T>());
            IMongoCollection<T> collection = GetCollection<T>();
            await collection.UpdateOneAsync<T>(filter, update);
        }
        public async Task UpdateManyAsync<T>(Expression<Func<T, bool>> filter, Func<UpdateDefinitionBuilder<T>, UpdateDefinition<T>> updateBuilder) 
        {
            var update = updateBuilder(new UpdateDefinitionBuilder<T>());
            IMongoCollection<T> collection = GetCollection<T>();
            await collection.UpdateManyAsync<T>(filter, update);
        }
        //查
        public async Task<T?> FindSingleAsync<T>(Expression<Func<T, bool>> filter)
        {
            IMongoCollection<T> collection = GetCollection<T>();
            return await collection.Find(filter).SingleOrDefaultAsync();
        }
        public async Task<List<T>> FindListAsync<T>(Expression<Func<T, bool>> filter)
        {
            IMongoCollection<T> collection = GetCollection<T>();
            return await collection.Find(filter).ToListAsync();
        }
        public async Task<bool> IsExistAsync<T>(Expression<Func<T, bool>> filter)
        {
            IMongoCollection<T> collection = GetCollection<T>();
            return await collection.Find(filter).AnyAsync<T>();
        }

        private string ConnectionStrGen(MongoDbConfig config)
        {
            return $"mongodb://{config.UserName}:{config.Pwd}@{config.Ip}:{config.Port}" +
                $"?authSource={config.AuthSource}&authMechanism={config.AuthMechanism}";
        }
    }
}
